package business

import (
	"context"
	"encoding/json"
	"github.com/streadway/amqp"
	"golang-manage-admin/providers"
	"golang-manage-admin/queue/publish"
)

type DeadLetterHandleQueue struct {
	Implementation
}

func (dlh *DeadLetterHandleQueue) Init() {
	//初始化重试脚本
	dlh.Implementation.Init()
}

/**
 * 配置文件名称
 */
func (dlh *DeadLetterHandleQueue) GetConfigKey() string {
	return "golang-manage-admin.dead.handle"
}

/**
 * 队列消费
 */
func (dlh *DeadLetterHandleQueue) Delivery(ctx context.Context, msg amqp.Delivery) {
	responseMode := ResponseMode{
		ResponseType: "ack",
	}
	defer dlh.Implementation.ReplyQueueHandler(responseMode, msg)

	//发送消息到
	sErr, responseMode := dlh.forwardMsg(msg)
	if sErr != nil {
		_ = dlh.logger.Errorf("消息处理失败:%+v", sErr.Error())
		return
	}

	return
}

/**
 * 消息重推
 */
func (dlh *DeadLetterHandleQueue) forwardMsg(msg amqp.Delivery) (error, ResponseMode) {
	data := new(QueueMsgBaseDataForm)
	// @Todo 消息解析
	if err := json.Unmarshal(msg.Body, data); err != nil {
		if string(msg.Body) != "" {
			_ = dlh.logger.Errorf("延时队列--消息解析失败:%s---%s", err.Error(), string(msg.Body))
		}
		return nil, ResponseMode{
			ResponseType: "ack",
		}
	}

	// 延迟处理-- 数据解析
	dlh.logger.Debugf("延时队列--事件处理接收解析DATA:%+v", data)

	// @Todo 判断重推次数（重推 or 失败）
	configTimes := providers.Config.GetInt32("publish.retry_times")
	var retryTimes int32 = 0
	headers := amqp.Table{}
	if _, exist := msg.Headers["retry_times"]; exist {
		retryTimes = msg.Headers["retry_times"].(int32)
		headers = msg.Headers
	}

	dlh.logger.Debugf("延时队列--当前处理次数retryTimes:%+s", retryTimes)

	if retryTimes >= configTimes {
		_ = dlh.logger.Errorf("延时队列--消息事件处理失败 队列重试已超过最大次数:%+v", data)
		// @Todo 推送到失败队列
		sendToFailedErr := publish.PublishObject.PushFormatWithHeader(publish.CFailed, data.Data, headers)
		if sendToFailedErr != nil {
			_ = dlh.logger.Errorf("延时队列--消息事件处理--推送失败队列失败:%+v", data)
			return nil, ResponseMode{
				ResponseType:   "retry",
				ToPublishKey:   publish.CDeadLetter,
				FromPublishKey: publish.CFailed,
			}
		} else {
			return nil, ResponseMode{
				ResponseType: "ack",
			}
		}

	}
	retryTimes += 1
	headers["retry_times"] = retryTimes
	sendToRetryErr := publish.PublishObject.PushFormatWithHeader(data.FromPublishKey, data.Data, headers)
	if sendToRetryErr != nil {
		_ = dlh.logger.Errorf("延时队列--消息事件处理--推送重推队列失败:%+v", data)
		return nil, ResponseMode{
			ResponseType:   "retry",
			ToPublishKey:   publish.CDeadLetter,
			FromPublishKey: publish.CFailed,
		}
	}
	return nil, ResponseMode{
		ResponseType: "ack",
	}
}
